/*
 * x86_64/cpuid.hh - CPUID wrapper.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#ifndef HEADER_X86_64_CPUID_HH
#define HEADER_X86_64_CPUID_HH

START_NAMESPACE (x86_64)

union cpuid_ext_feats_t
{
  enum fn_t
  {
    FN0 = 0x80000000,
    FN1 = FN0 + 1
  };

  struct
    {
      u32_t X87 : 1;
      u32_t VME : 1;
      u32_t DE : 1;
      u32_t PSE : 1;
      u32_t TSC : 1;
      u32_t MSR : 1;
      u32_t PAE : 1;
      u32_t MCE : 1;
      u32_t CMBXHG8B : 1;
      u32_t APIC : 1;
      u32_t : 1;
      u32_t SYSCALL_SYSRET: 1;
      u32_t MTRR : 1;
      u32_t PGE : 1;
      u32_t MCA : 1;
      u32_t CMI : 1;
      u32_t PAT : 1;
      u32_t : 3;
      u32_t NX : 1;
      u32_t : 3;
      u32_t FXSAVE_FXRSTOR : 1;
      u32_t FAST_FXSAVE_FXRSTOR : 1;
      u32_t : 3;
      u32_t LM : 1;
      u32_t : 2;
    };
  u32_t raw;

  INLINE
  static cpuid_ext_feats_t
  get ()
  {
    cpuid_ext_feats_t result;
    asm volatile (
      "cpuid\n"
      : "=d"(result.raw)
      : "a"(FN1)
      : "ebx", "ecx" );
    return result;
  }

  INLINE
  static u32_t
  get_max_fn ()
  {
    u32_t result;
    asm volatile (
      "cpuid\n"
      : "=a"(result)
      : "a"(FN0)
      : "ebx", "ecx", "edx"
    );
    return result;
  }
};

END_NAMESPACE

#endif /* HEADER_X86_64_CPUID_HH */

